package com.yanqu.road.dataHelper.repair.logic;

import com.yanqu.road.dao.db.DbParameter;
import com.yanqu.road.dataHelper.gameServer.GameServer;
import com.yanqu.road.dataHelper.repair.BaseRepair;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.xmlbeans.impl.common.ConcurrentReaderHashMap;

import java.math.BigInteger;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ChildEarnSpeedTask extends BaseRepair {
    public ChildEarnSpeedTask(GameServer gameServer) {
        super(gameServer);
    }

    @Override
    public void repair(long param1, String param2) {
        long t1 = System.currentTimeMillis();
        boolean result = updateMarriageRecord();
        if(!result){
            getLogger().error("updateMarriageRecord fail");
            return;
        }
        long t2 = System.currentTimeMillis();
        getLogger().error("{}-updateMarriageRecord cost time : {}", getGameServer().getServerInfo().getServerId(), t2 - t1);

        result = updateMarriage();
        if(!result){
            getLogger().error("updateMarriage fail");
            return;
        }
        long t3 = System.currentTimeMillis();
        getLogger().error("{}-updateMarriage cost time : {}", getGameServer().getServerInfo().getServerId(), t3 - t2);

        result = updateMarriageLonely();
        if(!result){
            getLogger().error("updateMarriageLonely fail");
            return;
        }
        long t4 = System.currentTimeMillis();
        getLogger().error("{}-updateMarriageLonely cost time : {}", getGameServer().getServerInfo().getServerId(), t4 - t3);

        Map<Long, BigInteger> userDataMap = sumUserChildEarnSpeed();
        if(userDataMap.size() <= 0){
            getLogger().error("sumUserChildEarnSpeed fail");
            return;
        }
        long t5 = System.currentTimeMillis();
        getLogger().error("{}-sumUserChildEarnSpeed cost time : {}", getGameServer().getServerInfo().getServerId(), t5 - t4);

        updateUserChildEarnSpeed(userDataMap);
        long t6 = System.currentTimeMillis();
        getLogger().error("{}-updateUserChildEarnSpeed cost time : {}", getGameServer().getServerInfo().getServerId(), t6 - t5);

        result = clearRankInfo();
        if(!result){
            getLogger().error("clearRankInfo fail");
        }
        long t7 = System.currentTimeMillis();
        getLogger().error("{}-clearRankInfo cost time : {}", getGameServer().getServerInfo().getServerId(), t7 - t6);

        result = clearPowerChildInfo();
        if(!result){
            getLogger().error("clearPowerChildInfo fail");
        }
        long t8 = System.currentTimeMillis();
        getLogger().error("{}-clearPowerChildInfo cost time : {}", getGameServer().getServerInfo().getServerId(), t8 - t7);

        result = updateUserHistory();
        if(!result){
            getLogger().error("updateUserHistory fail");
        }
        long t9 = System.currentTimeMillis();
        getLogger().error("{}-updateUserHistory cost time : {}", getGameServer().getServerInfo().getServerId(), t9 - t8);
        getLogger().error("{}-total cost time : {}", getGameServer().getServerInfo().getServerId(), t9 - t1);
    }

    /**
     * 更新联姻记录表
     * @return
     */
    private boolean updateMarriageRecord(){
        boolean result = false;
        String sql = "UPDATE t_u_marriage_record SET childEarnSpeed = ROUND(CASE WHEN childTalent=10001 THEN childEarnSpeed/10 WHEN childTalent=10002 THEN childEarnSpeed/15 WHEN childTalent=10003 THEN \n" +
                "childEarnSpeed/25 WHEN childTalent=10004 THEN childEarnSpeed/35 WHEN childTalent=10005 THEN childEarnSpeed/40 WHEN childTalent=10006 THEN childEarnSpeed/75\n" +
                " WHEN childTalent=10007 THEN childEarnSpeed/200 WHEN childTalent=10008 THEN childEarnSpeed/400 WHEN childTalent=10009 THEN childEarnSpeed/950 END),\n" +
                "partnerChildEarnSpeed = ROUND(CASE WHEN partnerChildTalent=10001 THEN partnerChildEarnSpeed/10 WHEN partnerChildTalent=10002 THEN partnerChildEarnSpeed/15 WHEN partnerChildTalent=10003 THEN \n" +
                "partnerChildEarnSpeed/25 WHEN partnerChildTalent=10004 THEN partnerChildEarnSpeed/35 WHEN partnerChildTalent=10005 THEN partnerChildEarnSpeed/40 WHEN partnerChildTalent=10006 THEN partnerChildEarnSpeed/75\n" +
                " WHEN partnerChildTalent=10007 THEN partnerChildEarnSpeed/200 WHEN partnerChildTalent=10008 THEN partnerChildEarnSpeed/400 WHEN partnerChildTalent=10009 THEN partnerChildEarnSpeed/950 END),\n" +
                "totalChildEarnSpeed=(CASE WHEN childEarnSpeed*10 > partnerChildEarnSpeed THEN childEarnSpeed+partnerChildEarnSpeed ELSE childEarnSpeed*11 END)";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            call = getConnection().prepareCall(sql);
            result = call.executeUpdate() > 0;
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
        return result;
    }

    /**
     * 更新联姻表（普通）
     * @return
     */
    private boolean updateMarriage(){
        boolean result = false;
        String sql = "UPDATE t_u_marriage SET childEarnSpeed = ROUND(CASE WHEN childTalent=10001 THEN childEarnSpeed/10 WHEN childTalent=10002 THEN childEarnSpeed/15 WHEN childTalent=10003 THEN \n" +
                "childEarnSpeed/25 WHEN childTalent=10004 THEN childEarnSpeed/35 WHEN childTalent=10005 THEN childEarnSpeed/40 WHEN childTalent=10006 THEN childEarnSpeed/75\n" +
                " WHEN childTalent=10007 THEN childEarnSpeed/200 WHEN childTalent=10008 THEN childEarnSpeed/400 WHEN childTalent=10009 THEN childEarnSpeed/950 END)\n" +
                "WHERE `status`=0 OR `status`=1";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            call = getConnection().prepareCall(sql);
            result = call.executeUpdate() > 0;
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
        return result;
    }

    /**
     * 更新联姻表（孤独终老）
     * @return
     */
    private boolean updateMarriageLonely(){
        boolean result = false;
        String sql = "UPDATE t_u_marriage SET childEarnSpeed = ROUND(CASE WHEN childTalent=10001 THEN childEarnSpeed/10 WHEN childTalent=10002 THEN childEarnSpeed/15 WHEN childTalent=10003 THEN \n" +
                "childEarnSpeed/40 WHEN childTalent=10004 THEN childEarnSpeed/80 WHEN childTalent=10005 THEN childEarnSpeed/100 WHEN childTalent=10006 THEN childEarnSpeed/200\n" +
                " WHEN childTalent=10007 THEN childEarnSpeed/600 WHEN childTalent=10008 THEN childEarnSpeed/1500 WHEN childTalent=10009 THEN childEarnSpeed/3500 END)\n" +
                "WHERE `status`=3";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            call = getConnection().prepareCall(sql);
            result = call.executeUpdate() > 0;
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
        return result;
    }

    /**
     * 联姻记录表求和
     * @return
     */
    private Map<Long, BigInteger> sumMarriageRecord(){
        ResultSet rs = null;
        CallableStatement call = null;
        Map<Long, BigInteger> dataMap = new ConcurrentHashMap<>();
        try {
            call = getGameServer().getConnection().prepareCall("select userId,totalChildEarnSpeed from t_u_marriage_record");
            rs = call.executeQuery();
            while (rs.next()) {
                long userId = rs.getLong("userId");
                BigInteger earnSpeed = BigInteger.ZERO;
                String value = rs.getString("totalChildEarnSpeed");
                if(!StringUtils.isNullOrEmpty(value)){
                    earnSpeed = new BigInteger(value);
                }
                BigInteger oldEarnSpeed = dataMap.get(userId);
                if(null == oldEarnSpeed){
                    oldEarnSpeed = BigInteger.ZERO;
                }
                dataMap.put(userId, oldEarnSpeed.add(earnSpeed));
            }
        } catch (SQLException e) {
            getLogger().error("异常错误", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
        return dataMap;
    }

    /**
     * 联姻表求和
     * @return
     */
    private Map<Long, BigInteger> sumMarriageLonely(){
        ResultSet rs = null;
        CallableStatement call = null;
        Map<Long, BigInteger> dataMap = new ConcurrentHashMap<>();
        try {
            call = getGameServer().getConnection().prepareCall("select userId,childEarnSpeed from t_u_marriage where `status`=3");
            rs = call.executeQuery();
            while (rs.next()) {
                long userId = rs.getLong("userId");
                BigInteger earnSpeed = BigInteger.ZERO;
                String value = rs.getString("childEarnSpeed");
                if(!StringUtils.isNullOrEmpty(value)){
                    earnSpeed = new BigInteger(value);
                }
                BigInteger oldEarnSpeed = dataMap.get(userId);
                if(null == oldEarnSpeed){
                    oldEarnSpeed = BigInteger.ZERO;
                }
                dataMap.put(userId, oldEarnSpeed.add(earnSpeed));
            }
        } catch (SQLException e) {
            getLogger().error("异常错误", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
        return dataMap;
    }

    /**
     * 玩家统计子嗣赚速
     * @return
     */
    private Map<Long, BigInteger> sumUserChildEarnSpeed(){
        Map<Long, BigInteger> dataMap = new ConcurrentReaderHashMap();
        List<Long> userIdList = getUserIdList();
        Map<Long, BigInteger> recordEarnSpeedMap = sumMarriageRecord();
        Map<Long, BigInteger> lonelyEarnSpeedMap = sumMarriageLonely();
        for(long userId : userIdList){
            BigInteger v1 = recordEarnSpeedMap.get(userId);
            if(null == v1){
                v1 = BigInteger.ZERO;
            }
            BigInteger v2 = lonelyEarnSpeedMap.get(userId);
            if(null == v2){
                v2 = BigInteger.ZERO;
            }
            dataMap.put(userId, v1.add(v2));
        }
        return dataMap;
    }

    /**
     * 更新玩家子嗣赚速
     * @param dataMap
     */
    private void updateUserChildEarnSpeed(Map<Long, BigInteger> dataMap){
        String sql = "update t_u_user set childEarnSpeed = ? where userId = ?";
        try {
            List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
            for (Map.Entry<Long, BigInteger> entry : dataMap.entrySet()) {
                int i = 1;
                Map<Integer, DbParameter> para = new HashMap<>();
                para.put(i++, new DbParameter(Types.VARCHAR, entry.getValue().toString()));
                para.put(i++, new DbParameter(Types.BIGINT, entry.getKey()));

                mapList.add(para);
            }
            getGameServer().executeBatchQuery(sql, mapList);
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
    }

    /**
     * 获取玩家编号数组
     * @return
     */
    private List<Long> getUserIdList(){
        List<Long> dataList = new ArrayList<>();
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            call = getGameServer().getConnection().prepareCall("select userId from t_u_user");
            rs = call.executeQuery();
            while (rs.next()) {
                long userId = rs.getLong("userId");
                dataList.add(userId);
            }
        } catch (SQLException e) {
            getLogger().error("异常错误", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
        return dataList;
    }

    /**
     * 清除赚速排行榜、清除子嗣排行榜
     * @return
     */
    private boolean clearRankInfo(){
        boolean result = false;
        String sql = "DELETE FROM t_u_rank WHERE type=1 OR type=8";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            call = getConnection().prepareCall(sql);
            result = call.executeUpdate() > 0;
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
        return result;
    }

    /**
     * 清除赚速排行榜、清除子嗣排行榜
     * @return
     */
    private boolean clearPowerChildInfo(){
        boolean result = false;
        String sql = "DELETE FROM t_u_power_child";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            call = getConnection().prepareCall(sql);
            result = call.executeUpdate() > 0;
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
        return result;
    }

    /**
     * 清除玩家历史最高赚速
     * @return
     */
    private boolean updateUserHistory(){
        boolean result = false;
        String sql = "UPDATE t_u_history_attribute SET earnSpeed='0'";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            call = getConnection().prepareCall(sql);
            result = call.executeUpdate() > 0;
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
        return result;
    }
}
